package com.ktz.shoping.myutils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

public class MyUtil {
	/**
	 * 
	 * 将Request参数转换为实体bean 要求：表单控件的name属性的值必须要和实体类的属性名一样（区分大小写） 具有文件上传处理功能
	 * 
	 * 
	 * 
	 * @param request
	 * 
	 *            request对象
	 * 
	 * @param clazz
	 * 
	 *            被转换的实体类类型
	 * 
	 * @param uploadFilePath
	 * 
	 *            文件上传服务器路径 例如："updatefiles/adminImgs/" 不进行文件上传处理，赋值 null
	 * 
	 * @param uploadFilePerfix
	 * 
	 *            上传文件的前缀 文件名格式：文件前缀_UUID随机码.文件后缀
	 * 
	 *            例如："admin_9d6ea285-09d9-4774-8cf3-7e898d7a0c53.png"
	 * 
	 *            不进行文件上传处理，赋值 null
	 * 
	 * @return 转换之后的实体类类型
	 * 
	 */
	public static <T> T convertRequestParameter2Bean(HttpServletRequest request, Class<T> clazz, String uploadFilePath,
			String uploadFilePerfix) {
		// 返回值

		T tBean = null;
		/*

		 * 由于使用beanutils时，从字符串转换为对象类型时，需要进行自定义的转换处理，也就是要自己写一个转换类

		 */
		// 注册自定义的日期类型转换器

		ConvertUtils.register(new DateTimeConverter(), Date.class);

		try {
			// 使用反射，获取被转换的实体类的实例变量

			tBean = clazz.newInstance();
			/************** 处理普通参数部分 begin***************/
			// 从request请求对象中获取所有的参数名的集合(不包括文件上传对象)

			Enumeration<String> enu = request.getParameterNames();
			// 遍历所有的request请求中的参数名

			while (enu.hasMoreElements()) {
				// 获取当前遍历的参数名

				String pName = enu.nextElement();
				// 通过参数名获取对应的参数值

				String pValue = request.getParameter(pName);
				// 把获取到的参数值 赋值给对应的实体类的属性

				Field pField = null;
				/*

				 * 使用反射，获取当前实体类的与参数名对应的属性对象，如果该属性对象没有，则不进行赋值操作

				 */
				try {
					pField = clazz.getDeclaredField(pName);
				} catch (NoSuchFieldException e) {
					// 在实体类中如果没有与表单name值对应的属性，则忽略转换，继续后面属性的处理

					continue;
				}
				// 如果获取到了属性对象，则进行赋值操作

				if (pField != null && pValue != null && !pValue.equals("")) {
					// 使用beanutils将改request请求参数的值复制到实体类对应名字的属性上

					/*

					 * BeanUtils.setProperty该方法完成的工作是：

					 * 将tBean实体类中名字为pName的属性赋值为pValue

					 */
					BeanUtils.setProperty(tBean, pName, pValue);
				}
			}
			/************** 处理普通参数部分  end***************/
			/************** 处理文件上传部分 begin***************/
			// 判断当前request请求是否进行文件上传处理；表单是否使用了 enctype="multipart/form-data"属性

			if (request.getContentType().split(";")[0].equals("multipart/form-data")) {
				// 获取文件上传对象集合

				Collection<Part> parts = request.getParts();
				// 一次处理每一个文件上传对象

				if (parts != null && parts.size() > 1) {
					for (Part part : parts) {
						// 获取文件控件的name属性的值

						String pName = part.getName();
						// 获取 MINE类型，普通控件的改属性是 null，文件上传控件的属性不是null

						String pContentType = part.getContentType();
						// 判断当前的part是否是进行文件上传处理

						if (pContentType != null && !pContentType.equals("") && part.getSize()>0) {
							// 将文件二进制字节流保存到服务器的指定目录下

							// 获取网站的根目录（相对于服务器的盘符）

							String realPath = request.getServletContext().getRealPath("/");
							// 获取文件上传是提交的文件名

							String fileSubmitName = part.getSubmittedFileName();
							// 提取保存文件的后缀类型

							String fileType = "."+pContentType.substring(pContentType.lastIndexOf('/')).replace("/", "");
							// 重新组合保存文件的文件名：文件前缀_随机码.文件后缀

							String fileSaveName = uploadFilePerfix + "_" + UUID.randomUUID().toString() + fileType;
							// 保存的文件路径（相对于根路径的文件路径名）

							String fileSavePath = uploadFilePath + fileSaveName;
							// 如果存储上传文件的文件夹不存在，则创建文件夹

							File f = new File(realPath + uploadFilePath);
							if (!f.exists()) {
								f.mkdirs();
							}
							// 上传文件

							part.write(realPath + fileSavePath);
							// 将文件保存的路径赋值给bean实体的属性

							if (fileSavePath != null && !fileSavePath.equals("")) {								
								BeanUtils.setProperty(tBean, pName, fileSavePath);
							}
						}
					}
				}
			}
			/************** 处理文件上传部分  end***************/
		} catch (Exception e) {
			// Request参数转换为实体bean异常

			e.printStackTrace();
		}

		// 返回值

		return tBean;
	}
}
